package list

// ref:
// Random Numbers https://gobyexample.com/random-numbers

import (
	"fmt"
	"math"
	"math/rand"
	"time"
)

// Definition for singly-linked list.
type ListNode struct {
	Val  int
	Next *ListNode
}

// Println print all elements from node n to the tail node.
func (n *ListNode) Println() string {
	res := ""
	for head := n; head != nil; head = head.Next {
		res += fmt.Sprintf("%d->", head.Val)
	}
	return res + "nil"
}

// Length return the length of linked list from node n to the tail node.
func (n *ListNode) Length() int {
	res := 0
	for head := n; head != nil; head = head.Next {
		res += 1
	}
	return res
}

// NewRandomList generate a random singly linked list.
func NewRandomList() *ListNode {
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	// make sure the array length is greater than 0
	length := r.Int()%math.MaxUint8 + 1
	dummy := &ListNode{}
	p := dummy
	for i := 0; i < length; i++ {
		tmp := &ListNode{Val: r.Intn(100), Next: nil}
		p.Next = tmp
		p = p.Next
	}
	// return singly linked-list head node
	return dummy.Next
}

// NewRandomList generate a random cycle singly linked list.
func NewRandomCycleList() *ListNode {
	r := rand.New(rand.NewSource(time.Now().UnixNano()))
	// make sure the array length is greater than 0
	length := r.Int()%math.MaxUint8 + 1
	collision_position := r.Intn(length - 1)
	var collision_point *ListNode
	dummy := &ListNode{}
	p := dummy
	for i := 0; i < length; i++ {
		if i == length-1 {
			p.Next = collision_point
			break
		}
		tmp := &ListNode{Val: r.Intn(100)}
		p.Next = tmp
		p = p.Next
		if i == collision_position {
			collision_point = p
		}
	}
	// return singly linked-list head node
	return dummy.Next
}
